package ua.khpi.si.kit49.diploma.core;

import java.util.ArrayList;
import java.util.List;

import ua.khpi.si.kit49.diploma.db.dto.City;
import ua.khpi.si.kit49.diploma.db.dto.RoadPriority;
import ua.khpi.si.kit49.diploma.db.dto.RoadQuality;

/**
 * Class for storage route and its features.
 * This class is uses in program to calculate best route.
 * 
 * @author netstalk3r
 * 
 */
public class Route implements Comparable<Route> {

	private Path path;
	private List<City> cities;
	private Integer lengthRoute;
	private RoadPriority averageRoadPriority;
	private Integer averageFlowIntensity;
	private RoadQuality averageRoadQuality;
	private Integer averageRoadWidth;
	private Weather averageWeather;

	public Route() {
		super();
		cities = new ArrayList<City>();
	}

	public Route(Path path, Integer lengthRoute,
			RoadPriority averageRoadPriority, Integer averageFlowIntensity,
			RoadQuality averageRoadQuality, Integer averageRoadWidth,
			Weather averageWeather) {
		super();
		this.path = path;
		this.lengthRoute = lengthRoute;
		this.averageRoadPriority = averageRoadPriority;
		this.averageFlowIntensity = averageFlowIntensity;
		this.averageRoadQuality = averageRoadQuality;
		this.averageRoadWidth = averageRoadWidth;
		this.averageWeather = averageWeather;
	}

	public Path getPath() {
		return path;
	}

	public void setPath(Path path) {
		this.path = path;
	}

	public List<City> getCities() {
		return cities;
	}

	public void setCities(List<City> cities) {
		this.cities = cities;
	}

	public Integer getLengthRoute() {
		return lengthRoute;
	}

	public void setLengthRoute(Integer lengthRoute) {
		this.lengthRoute = lengthRoute;
	}

	public RoadPriority getAverageRoadPriority() {
		return averageRoadPriority;
	}

	public void setAverageRoadPriority(RoadPriority averageRoadPriority) {
		this.averageRoadPriority = averageRoadPriority;
	}

	public Integer getAverageFlowIntensity() {
		return averageFlowIntensity;
	}

	public void setAverageFlowIntensity(Integer averageFlowIntensity) {
		this.averageFlowIntensity = averageFlowIntensity;
	}

	public RoadQuality getAverageRoadQuality() {
		return averageRoadQuality;
	}

	public void setAverageQuality(RoadQuality averageRoadQuality) {
		this.averageRoadQuality = averageRoadQuality;
	}

	public Integer getAverageRoadWidth() {
		return averageRoadWidth;
	}

	public void setAverageRoadWidth(Integer averageRoadWidth) {
		this.averageRoadWidth = averageRoadWidth;
	}

	public Weather getAverageWeather() {
		return averageWeather;
	}

	public void setAverageWeather(Weather averageWeather) {
		this.averageWeather = averageWeather;
	}
	
	@Override
	public int hashCode() {
		int hash = 29;
		hash = hash * 19 + ((path == null) ? 0 : path.hashCode());
		hash = hash * 19 + ((lengthRoute == null) ? 0 : lengthRoute.hashCode());
		hash = hash
				* 19
				+ ((averageRoadPriority == null) ? 0 : averageRoadPriority
						.hashCode());
		hash = hash
				* 19
				+ ((averageFlowIntensity == null) ? 0 : averageFlowIntensity
						.hashCode());
		hash = hash
				* 19
				+ ((averageRoadQuality == null) ? 0 : averageRoadQuality
						.hashCode());
		hash = hash
				* 19
				+ ((averageRoadWidth == null) ? 0 : averageRoadWidth.hashCode());
		hash = hash * 19
				+ ((averageWeather == null) ? 0 : averageWeather.hashCode());
		return hash;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Route))
			return false;
		Route entry = (Route) obj;
		return path.equals(entry.getPath())
				&& lengthRoute.equals(entry.getLengthRoute())
				&& averageRoadPriority.equals(entry.getAverageRoadPriority())
				&& averageFlowIntensity.equals(entry.getAverageFlowIntensity())
				&& averageRoadQuality.equals(entry.getAverageRoadQuality())
				&& averageRoadWidth.equals(entry.getAverageRoadWidth())
				&& averageWeather.equals(entry.getAverageWeather());
	}

	@Override
	public int compareTo(Route compareRoute) {
		int result = this.lengthRoute - compareRoute.getLengthRoute();
		if (result != 0)
			return (int) (result / Math.abs(result));
		result = this.averageRoadPriority.compareTo(compareRoute
				.getAverageRoadPriority());
		if (result != 0)
			return (int) (result / Math.abs(result));
		result = compareRoute.getAverageFlowIntensity()
				- this.averageFlowIntensity;
		if (result != 0)
			return (int) (result / Math.abs(result));
		result = this.averageRoadQuality.compareTo(compareRoute
				.getAverageRoadQuality());
		if (result != 0)
			return (int) (result / Math.abs(result));
		result = compareRoute.getAverageRoadWidth() - this.averageRoadWidth;
		if (result != 0)
			return (int) (result / Math.abs(result));
		result = this.averageWeather
				.compareTo(compareRoute.getAverageWeather());
		return (result != 0) ? (int) (result / Math.abs(result)) : 0;
	}
}
